from sqlalchemy import Column, Integer, String, DateTime, Text, create_engine
from sqlalchemy.orm import declarative_base, sessionmaker
from datetime import datetime
from zoneinfo import ZoneInfo
import os

DATABASE_URL = "sqlite:///email_server.db"

Base = declarative_base()

class MailLog(Base):
    __tablename__ = "mail_logs"
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键ID
    timestamp = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 记录时间（本地时区）
    direction = Column(String(16), nullable=False)  # 流向（incoming/outgoing）
    username = Column(String(128), nullable=True)  # 调用者用户名
    to = Column(String(255), nullable=True)  # 收件人邮箱
    subject = Column(String(512), nullable=True)  # 邮件主题
    provider = Column(String(32), nullable=False)  # 提供方（graph/qq 等）
    status = Column(String(16), nullable=False)  # 状态（success/failed）
    error_code = Column(String(64), nullable=True)  # 错误码
    error_message = Column(Text, nullable=True)  # 错误信息
    request_id = Column(String(64), nullable=True)  # 请求ID（Graph 返回）
    latency_ms = Column(Integer, nullable=True)  # 发送耗时（毫秒）
    body_preview = Column(Text, nullable=True)  # 正文预览（截断）
    attachments_count = Column(Integer, nullable=True)  # 附件数量
    attachments_json = Column(Text, nullable=True)  # 附件名称列表（JSON）
    from_email = Column(String(255), nullable=True)  # 发件人（代理）
    body_type = Column(String(16), nullable=True)  # 正文类型（Text/HTML）
    to_json = Column(Text, nullable=True)  # 多收件人列表（JSON）
    cc_json = Column(Text, nullable=True)  # 抄送列表（JSON）
    bcc_json = Column(Text, nullable=True)  # 密送列表（JSON）

class TokenEvent(Base):
    __tablename__ = "token_events"
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键ID
    timestamp = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 事件时间（本地时区）
    event = Column(String(64), nullable=False)  # 事件类型（verify_ok/refresh_ok/...）
    detail = Column(Text, nullable=True)  # 事件详情（JSON或文本）

class OAuthCallback(Base):
    __tablename__ = "oauth_callbacks"
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键ID
    timestamp = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 回调时间（本地时区）
    code = Column(Text, nullable=False)  # 授权码
    state = Column(String(256), nullable=True)  # 状态参数
    session_state = Column(String(256), nullable=True)  # 会话状态
    activated = Column(String(16), nullable=False)  # 是否激活（true/false 字符串）

class ApiCall(Base):
    __tablename__ = "api_calls"
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键ID
    timestamp = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 请求时间（本地时区）
    endpoint = Column(String(255), nullable=False)  # 端点路径
    method = Column(String(16), nullable=False)  # 请求方法（GET/POST/...）
    status_code = Column(Integer, nullable=False)  # 响应状态码
    duration_ms = Column(Integer, nullable=True)  # 请求耗时（毫秒）
    request_summary = Column(Text, nullable=True)  # 请求摘要（截断）
    response_summary = Column(Text, nullable=True)  # 响应摘要（截断）

engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)

def init_db():
    """
    初始化数据库并进行轻量迁移，确保 mail_logs 表包含附件相关字段
    """
    Base.metadata.create_all(bind=engine)
    try:
        with engine.connect() as conn:
            cols = conn.exec_driver_sql("PRAGMA table_info(mail_logs)").fetchall()
            existing = {row[1] for row in cols}
            if "username" not in existing:
                conn.exec_driver_sql("ALTER TABLE mail_logs ADD COLUMN username VARCHAR(128)")
            if "from_email" not in existing:
                conn.exec_driver_sql("ALTER TABLE mail_logs ADD COLUMN from_email VARCHAR(255)")
            if "body_type" not in existing:
                conn.exec_driver_sql("ALTER TABLE mail_logs ADD COLUMN body_type VARCHAR(16)")
            if "to_json" not in existing:
                conn.exec_driver_sql("ALTER TABLE mail_logs ADD COLUMN to_json TEXT")
            if "cc_json" not in existing:
                conn.exec_driver_sql("ALTER TABLE mail_logs ADD COLUMN cc_json TEXT")
            if "bcc_json" not in existing:
                conn.exec_driver_sql("ALTER TABLE mail_logs ADD COLUMN bcc_json TEXT")
            if "attachments_count" not in existing:
                conn.exec_driver_sql("ALTER TABLE mail_logs ADD COLUMN attachments_count INTEGER")
            if "attachments_json" not in existing:
                conn.exec_driver_sql("ALTER TABLE mail_logs ADD COLUMN attachments_json TEXT")
            # 轻量迁移 oauth_callbacks 表，若不存在则创建（Create 已覆盖），否则跳过
            # 轻量检查 email_accounts 是否存在（Create 已覆盖）
        # 初始化 token_status 默认记录
        with SessionLocal() as s:
            from sqlalchemy import select
            exists = s.execute(select(TokenStatus).where(TokenStatus.provider == "graph")).first()
            if not exists:
                s.add(TokenStatus(provider="graph", status="normal", last_check_at=datetime.utcnow(), updated_at=datetime.utcnow()))
                s.commit()
            # 可选：如果没有默认邮箱配置，则不强制插入，等待用户通过接口配置
    except Exception:
        pass

# 时区与本地时间工具
_TZ = os.getenv("TZ", "Asia/Shanghai")

def get_now_local() -> datetime:
    """
    返回本地时区时间（naive，本地墙钟时间），默认 Asia/Shanghai。
    """
    try:
        return datetime.now(ZoneInfo(_TZ)).replace(tzinfo=None)
    except Exception:
        return datetime.now()

class TokenStatus(Base):
    __tablename__ = "token_status"
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键ID
    provider = Column(String(64), nullable=False, unique=True)  # 提供方标识（如 graph）
    status = Column(String(32), nullable=False)  # 状态（normal/invalid/updating/error）
    last_check_at = Column(DateTime, nullable=True)  # 最近验证时间
    updated_at = Column(DateTime, nullable=True)  # 状态更新时间
    lock_owner = Column(String(128), nullable=True)  # 锁持有者（实例名/主机名）
    lock_expire_at = Column(DateTime, nullable=True)  # 锁过期时间
    note = Column(Text, nullable=True)  # 备注
    
class EmailAccount(Base):
    __tablename__ = "email_accounts"
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键ID
    sender_email = Column(String(255), nullable=False, unique=True)  # 发件邮箱（旧结构）
    cc_emails = Column(Text, nullable=True)  # 抄送邮箱列表（JSON 字符串，旧结构）
    proxy_email = Column(String(255), nullable=True)  # 代理邮箱（旧结构）
    is_default = Column(Integer, nullable=False, default=0)  # 是否默认（0/1，旧结构）
    created_at = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 创建时间（本地时区）
    updated_at = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 更新时间（本地时区）

class EmailEntry(Base):
    __tablename__ = "email_entries"
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键ID
    email = Column(String(255), nullable=False)  # 邮箱地址
    type = Column(String(32), nullable=False)  # 类型（sender/cc/proxy）
    is_default = Column(Integer, nullable=False, default=0)  # 是否默认（0/1，仅 sender/proxy 生效）
    create_time = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 创建时间（本地时区）
    update_time = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 更新时间（本地时区）

class SendWhitelist(Base):
    __tablename__ = "send_whitelist"
    id = Column(Integer, primary_key=True, autoincrement=True)  # 主键ID
    type = Column(String(16), nullable=False)  # 类型（ip/cidr/domain）
    value = Column(String(255), nullable=False)  # 白名单值（IP/网段/域名）
    enabled = Column(Integer, nullable=False, default=1)  # 是否启用（0/1）
    note = Column(Text, nullable=True)  # 备注
    created_at = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 创建时间（本地时区）
    updated_at = Column(DateTime, default=lambda: get_now_local(), nullable=False)  # 更新时间（本地时区）
